MkDocs Architecture - Monolithic vs. Modular Deployment
MkDocs Monolithic vs. Modular Deployment
📋 Table of Contents
- 📖 Overview
- 🏗️ Monolithic vs. Modular Deployment
- 🔧 Deployment Strategies
- 📊 Architecture Comparison Matrix
- 🗺️ Implementation Roadmap
- ⚙️ Technical Implementation Details
- ⚖️ Benefits and Trade-offs Analysis
- 💡 Recommendations
- 📖 References
- 📊 Appendix A: Quarto vs MkDocs Comparison
📖 Overview
This document focuses specifically on deployment architecture strategies for MkDocs documentation sites, exploring how to move from monolithic deployment to modular approaches where content sections can be built and deployed independently.
Note: For understanding how MkDocs’ core architecture and rendering works, see 001.001 Architecture - How MkDocs works.md.
Key Questions Addressed:
- Can individual pages or sections be built independently from the full site?
- How can multi-site documentation be deployed as a unified experience?
- What are the performance implications of different deployment approaches?
- When should you consider modular vs. monolithic deployment strategies?
Real-World Context:
MkDocs is designed as a monolithic build system, but several strategies exist for scaling large documentation sites while maintaining fast build times and independent deployment cycles.
🏗️ Monolithic vs. Modular Deployment
Default Monolithic Approach
MkDocs’ default deployment follows a monolithic pattern where all content deploys together:
┌─────────────────────────────────────────────────────────────────┐
│ MkDocs Monolithic Build │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │mkdocs.yml│───▶│Configuration│───▶│ File │ │
│ │ │ │ Loading │ │ Discovery │ │
│ └──────────┘ └─────────────┘ └──────┬──────┘ │
│ │ │
│ ┌──────────┐ │ │
│ │ docs/ │─────────────────────────────▶│ │
│ │ *.md │ │ │
│ └──────────┘ ▼ │
│ ┌─────────────┐ │
│ │ Navigation │ │
│ │ Builder │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Render │ │
│ │ All Pages │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ site/ │ │
│ │ (Output) │ │
│ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Deploy │ │
│ │ Single │ │
│ │ Bundle │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Monolithic Characteristics:
- Atomic Builds: All pages rendered at each deployment
- Consistent State: Navigation always matches available content
- Single Configuration: One
mkdocs.ymlcontrols everything - Simple Deployment: Output is a single directory to deploy
Example Monolithic Configuration:
# mkdocs.yml - Everything builds together
site_name: My Documentation
docs_dir: docs
site_dir: site
nav:
- Home: index.md
- Getting Started: getting-started.md
- User Guide:
- Installation: user-guide/installation.md
- Configuration: user-guide/configuration.md
- API Reference:
- Overview: api/index.md
- Endpoints: api/endpoints.mdWhen Sites Grow: Scalability Challenges
As MkDocs sites grow in size and complexity, the monolithic approach can become a bottleneck:
Common Pain Points:
| Issue | Impact | Threshold |
|---|---|---|
| Build Time | Developer productivity | > 30 seconds |
| CI/CD Duration | Deployment frequency | > 5 minutes |
| Team Conflicts | Collaboration friction | > 3 contributors |
| Content Volume | Resource consumption | > 200 pages |
When to Consider Modular Approaches:
- Build times consistently exceed 30 seconds to 1 minute
- Multiple teams contributing content simultaneously
- High-frequency updates (multiple times per day)
- Large content volume (300+ pages)
- Independent versioning requirements for different sections
🔧 Deployment Strategies
Strategy 1: Configuration Inheritance
Concept: Use MkDocs’ INHERIT feature to share common configuration across multiple documentation sites.
# base.yml - Shared configuration
theme:
name: material
palette:
primary: indigo
markdown_extensions:
- admonition
- codehilite
- toc:
permalink: true
plugins:
- search# project-a/mkdocs.yml
INHERIT: ../base.yml
site_name: Project A Documentation
site_url: https://docs.example.com/project-a/
docs_dir: docs
site_dir: site
nav:
- Home: index.md
- Guide: guide.md# project-b/mkdocs.yml
INHERIT: ../base.yml
site_name: Project B Documentation
site_url: https://docs.example.com/project-b/
docs_dir: docs
site_dir: site
nav:
- Home: index.md
- API: api.mdFile Structure:
documentation/
├── base.yml # Shared configuration
├── project-a/
│ ├── mkdocs.yml # Inherits from base.yml
│ ├── docs/
│ │ ├── index.md
│ │ └── guide.md
│ └── site/ # Built output
├── project-b/
│ ├── mkdocs.yml # Inherits from base.yml
│ ├── docs/
│ │ ├── index.md
│ │ └── api.md
│ └── site/ # Built output
└── deploy/ # Combined deployment
├── project-a/
└── project-b/
Benefits:
- ✅ Consistent styling across all documentation
- ✅ Independent builds for each project
- ✅ Shared maintenance of common configuration
- ✅ Selective deployment of individual projects
Strategy 3: Monorepo with Selective Builds
Concept: Single repository with multiple documentation sections, using CI/CD to build only changed sections.
# .github/workflows/docs.yml
name: Build Documentation
on:
push:
paths:
- 'docs/**'
- 'mkdocs.yml'
jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
sections: ${{ steps.changes.outputs.sections }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- id: changes
run: |
# Detect which sections changed
CHANGED_SECTIONS=$(git diff --name-only HEAD~1 | grep '^docs/' | cut -d'/' -f2 | sort -u | jq -R -s -c 'split("\n") | map(select(length > 0))')
echo "sections=$CHANGED_SECTIONS" >> $GITHUB_OUTPUT
build:
needs: detect-changes
runs-on: ubuntu-latest
strategy:
matrix:
section: ${{ fromJson(needs.detect-changes.outputs.sections) }}
steps:
- uses: actions/checkout@v4
- name: Build section
run: |
pip install mkdocs mkdocs-material
mkdocs build --config-file docs/${{ matrix.section }}/mkdocs.ymlFile Structure:
monorepo/
├── docs/
│ ├── api/
│ │ ├── mkdocs.yml
│ │ └── docs/
│ ├── guides/
│ │ ├── mkdocs.yml
│ │ └── docs/
│ └── tutorials/
│ ├── mkdocs.yml
│ └── docs/
├── .github/
│ └── workflows/
│ └── docs.yml
└── scripts/
└── build-all.sh
Strategy 4: Plugin-Based Modular Architecture
Concept: Use MkDocs plugins to dynamically include content from multiple sources.
# mkdocs.yml with monorepo plugin
site_name: Unified Documentation
plugins:
- search
- monorepo:
# Include documentation from subprojects
docs_dir: docs/
nav:
- Home: index.md
- API: '!include ./api/mkdocs.yml'
- Guides: '!include ./guides/mkdocs.yml'Popular Plugins for Modular Documentation:
| Plugin | Purpose |
|---|---|
mkdocs-monorepo-plugin |
Include docs from multiple directories |
mkdocs-multirepo-plugin |
Pull docs from multiple repositories |
mkdocs-awesome-pages-plugin |
Simplify navigation configuration |
mkdocs-include-markdown-plugin |
Include markdown from external files |
Strategy 5: Versioned Documentation
Concept: Maintain multiple versions of documentation with version switching.
# mkdocs.yml with mike versioning
site_name: My Library
site_url: https://docs.example.com/
plugins:
- search
- mike:
version_selector: true
css_dir: css
javascript_dir: js
extra:
version:
provider: mikeDeployment Commands:
# Deploy version 1.0
mike deploy --push --update-aliases 1.0 latest
# Deploy version 2.0
mike deploy --push --update-aliases 2.0 latest
# Set default version
mike set-default --push latestGenerated Structure:
site/
├── 1.0/
│ ├── index.html
│ └── ...
├── 2.0/
│ ├── index.html
│ └── ...
├── latest -> 2.0/
└── versions.json
📊 Architecture Comparison Matrix
| Aspect | Monolithic | Config Inheritance | Multi-Site | Monorepo | Plugin-Based |
|---|---|---|---|---|---|
| Build Speed | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| Complexity | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| Consistency | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Team Independence | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| Search Integration | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Maintenance | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
| Best For | Small-Medium | Enterprise | Multi-product | Large teams | Versioning |
🗺️ Implementation Roadmap
Phase 1: Assessment (1 week)
Objectives:
- Measure current build performance
- Identify content update patterns
- Map team workflows and pain points
Deliverables:
assessment/
├── build-metrics.md # Current build times
├── content-analysis.md # Update frequency by section
├── team-survey.md # Developer pain points
└── recommendations.md # Strategy selection
Phase 2: Proof of Concept (2 weeks)
Objectives:
- Implement chosen strategy on subset of content
- Validate performance improvements
- Test team workflows
Success Criteria:
- Build time reduction: > 50% for targeted content
- Deployment independence: Sections deploy separately
- No functionality loss: All features work correctly
Phase 3: Migration (2-4 weeks)
Objectives:
- Migrate production content to new architecture
- Update CI/CD pipelines
- Train team on new workflows
Migration Steps:
- Prepare infrastructure
- Set up new repository structure
- Configure CI/CD pipelines
- Create deployment scripts
- Migrate content incrementally
- Start with least-critical sections
- Validate each migration
- Update internal links
- Switch over
- Deploy new architecture
- Monitor for issues
- Roll back if needed
⚙️ Technical Implementation Details
GitHub Pages Deployment Script
# .github/workflows/deploy-multi-site.yml
name: Deploy Documentation
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
site: [api, guides, tutorials]
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install mkdocs mkdocs-material
- name: Build ${{ matrix.site }}
run: |
cd docs/${{ matrix.site }}
mkdocs build --site-dir ../../output/${{ matrix.site }}
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.site }}
path: output/${{ matrix.site }}
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
uses: actions/download-artifact@v3
with:
path: site
- name: Create index
run: |
cat > site/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head><title>Documentation</title></head>
<body>
<h1>Documentation</h1>
<ul>
<li><a href="/api/">API Reference</a></li>
<li><a href="/guides/">User Guides</a></li>
<li><a href="/tutorials/">Tutorials</a></li>
</ul>
</body>
</html>
EOF
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./siteCombined Search Index Script
# scripts/combine_search.py
"""Combine search indexes from multiple MkDocs sites."""
import json
import os
from pathlib import Path
def combine_search_indexes(site_dirs: list[str], output_path: str):
"""Combine search indexes from multiple sites."""
combined = {
'config': {'lang': ['en']},
'docs': []
}
for site_dir in site_dirs:
index_path = Path(site_dir) / 'search' / 'search_index.json'
if index_path.exists():
with open(index_path) as f:
site_index = json.load(f)
# Prefix URLs with site path
site_name = Path(site_dir).name
for doc in site_index.get('docs', []):
doc['location'] = f'/{site_name}/{doc["location"]}'
combined['docs'].append(doc)
# Write combined index
output_file = Path(output_path) / 'search' / 'search_index.json'
output_file.parent.mkdir(parents=True, exist_ok=True)
with open(output_file, 'w') as f:
json.dump(combined, f)
if __name__ == '__main__':
combine_search_indexes(
site_dirs=['output/api', 'output/guides', 'output/tutorials'],
output_path='output'
)⚖️ Benefits and Trade-offs Analysis
Benefits of Modular Architecture
Performance Improvements:
- ✅ Faster builds: Only build changed sections
- ✅ Parallel processing: Build sections concurrently
- ✅ Reduced CI/CD time: Targeted deployments
- ✅ Better caching: Cache per-section artifacts
Development Experience:
- ✅ Team independence: Teams own their documentation
- ✅ Reduced conflicts: Fewer merge conflicts
- ✅ Faster iteration: Quick feedback loops
- ✅ Clear ownership: Section-based responsibility
Trade-offs and Challenges
Increased Complexity:
- ⚠️ Multiple configurations: More files to maintain
- ⚠️ Cross-site navigation: Requires custom solutions
- ⚠️ Search integration: May need custom search
- ⚠️ Deployment orchestration: More complex CI/CD
Consistency Challenges:
- ⚠️ Styling drift: Sections may diverge visually
- ⚠️ Version mismatches: Different MkDocs versions
- ⚠️ Link validation: Cross-site links harder to validate
- ⚠️ SEO considerations: Multiple sitemaps to manage
💡 Recommendations
Decision Framework
┌────────────────────────────────────────┐
│ Site Size Assessment │
└───────────────────┬────────────────────┘
│
┌───────────────────┴────────────────────┐
│ │
< 100 pages > 100 pages
│ │
▼ ▼
┌───────────────┐ ┌────────────────────┐
│ Monolithic │ │ Build time > 30s? │
│ Approach │ └─────────┬──────────┘
└───────────────┘ │
┌───────────┴───────────┐
│ │
Yes No
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Multiple teams? │ │ Monolithic │
└────────┬────────┘ │ + Caching │
│ └─────────────────┘
┌─────────┴─────────┐
│ │
Yes No
│ │
▼ ▼
┌────────────────┐ ┌────────────────┐
│ Multi-Site │ │ Monorepo + │
│ Architecture │ │ Selective Build│
└────────────────┘ └────────────────┘
Recommended Approach by Scenario
| Scenario | Recommendation |
|---|---|
| Single team, < 100 pages | Monolithic |
| Single team, 100-300 pages | Monolithic + caching |
| Multiple teams, shared product | Config inheritance |
| Multiple products | Multi-site architecture |
| Versioned documentation | Mike plugin |
| Large enterprise | Monorepo with selective builds |
📖 References
Official Documentation
- MkDocs Configuration - Official configuration reference
- MkDocs Deployment - Deployment strategies
- GitHub Pages - GitHub hosting documentation
Plugins and Tools
- mkdocs-monorepo-plugin - Monorepo support
- mike - Version management
- mkdocs-multirepo-plugin - Multi-repository docs
📊 Appendix A: Quarto vs MkDocs Comparison
This appendix provides a detailed comparison between Quarto and MkDocs to help teams choose the right documentation tool.
Overview Comparison
| Aspect | Quarto | MkDocs |
|---|---|---|
| Primary Language | Multiple (R, Python, Julia, JS) | Python |
| Configuration Format | YAML (_quarto.yml) |
YAML (mkdocs.yml) |
| Template Engine | Pandoc + Lua filters | Jinja2 |
| Markdown Processor | Pandoc | Python-Markdown |
| Primary Use Case | Scientific/Technical publishing | Project documentation |
| Learning Curve | Moderate-Steep | Easy-Moderate |
Feature Comparison
| Feature | Quarto | MkDocs |
|---|---|---|
| Static HTML Generation | ✅ Yes | ✅ Yes |
| Live Preview Server | ✅ Yes | ✅ Yes |
| Built-in Search | ✅ Yes | ✅ Yes (Lunr.js) |
| Code Execution | ✅ Yes (R, Python, Julia) | ❌ No (static only) |
| PDF Generation | ✅ Yes (via LaTeX) | ⚠️ Via plugins |
| Jupyter Notebook Support | ✅ Native | ⚠️ Via plugins |
| Reveal.js Presentations | ✅ Built-in | ❌ No |
| Multi-format Output | ✅ HTML, PDF, Word, ePub | ✅ HTML only |
| Cross-references | ✅ Built-in | ⚠️ Via plugins |
| Citations/Bibliography | ✅ Built-in | ⚠️ Via plugins |
| GitHub Pages Deploy | ✅ Via Actions | ✅ Built-in command |
| Plugin Ecosystem | Growing | Mature |
| Theme Variety | Limited | Extensive |
Architecture Comparison
Quarto Architecture
Source Files (.qmd, .md, .ipynb)
│
▼
┌─────────────────┐
│ Pandoc │◀──── Lua Filters
│ (Converter) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Knitr/Jupyter │ (Optional: Code Execution)
│ Engine │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Output Format │
│ (HTML/PDF/etc.) │
└─────────────────┘
MkDocs Architecture
Source Files (.md)
│
▼
┌─────────────────┐
│ Python-Markdown │◀──── Extensions
│ (Converter) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Jinja2 │◀──── Theme Templates
│ Templates │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Static HTML │
└─────────────────┘
When to Choose Quarto
✅ Choose Quarto when:
- You need executable code in documentation (R, Python, Julia)
- You’re creating scientific or academic content
- You need multiple output formats (HTML, PDF, Word, ePub)
- You work with Jupyter notebooks extensively
- You need built-in cross-references and citations
- You’re creating presentations alongside documentation
- You need LaTeX-quality mathematical typesetting
When to Choose MkDocs
✅ Choose MkDocs when:
- You’re documenting a software project
- You need fast, simple static site generation
- You want a mature plugin ecosystem
- You prefer Python-based tooling
- You need extensive theme options (Material for MkDocs)
- You value simplicity over features
- Your team is familiar with Python/Jinja2
Performance Comparison
| Metric | Quarto | MkDocs |
|---|---|---|
| Build Speed (100 pages) | 15-30 seconds | 5-10 seconds |
| Build Speed (500 pages) | 60-120 seconds | 30-60 seconds |
| Memory Usage | Higher (Pandoc) | Lower |
| Incremental Builds | Limited | Yes (via serve) |
| Cold Start Time | Slower | Faster |
Integration Comparison
| Integration | Quarto | MkDocs |
|---|---|---|
| GitHub Actions | Official action | Multiple options |
| GitLab CI | Good support | Excellent support |
| Read the Docs | Not native | Native support |
| VS Code | Official extension | Community extensions |
| RStudio | Native integration | N/A |
Migration Considerations
From Quarto to MkDocs
- Remove code execution blocks
- Convert
.qmdfiles to.md - Adapt cross-references syntax
- Replace callouts with admonitions
- Update configuration format
From MkDocs to Quarto
- Rename
.mdto.qmd(optional) - Update configuration to
_quarto.yml - Replace admonitions with callouts
- Update internal link syntax
- Adapt theme/styling approach
Summary Recommendation
| Scenario | Recommendation |
|---|---|
| Software project docs | MkDocs |
| Data science documentation | Quarto |
| API documentation | MkDocs |
| Research papers/books | Quarto |
| Corporate knowledge base | MkDocs |
| Educational content | Quarto |
| Simple project README → website | MkDocs |
| Multi-format publishing | Quarto |
Document Status: ✅ Complete | Last Updated: 2025-12-16 | Version: 1.0
This deployment architecture analysis provides a comprehensive foundation for making informed decisions about MkDocs site scaling strategies and comparing MkDocs with Quarto for documentation needs.